# -*- coding: utf-8 -*-

import subprocess
import time
import os
import logging
import threading
from datetime import datetime
from dingtalkchatbot.chatbot import DingtalkChatbot
from concurrent.futures import ThreadPoolExecutor

# 配置日志记录
logging.basicConfig(
    filename="transfer.log",
    level=logging.ERROR,
    format="%(asctime)s - %(levelname)s - %(message)s",
)

# 定义源服务器和目标服务器的信息
source_server = {"host": "103.233.10.138", "port": "13901"}

# 创建ThreadPoolExecutor
executor = ThreadPoolExecutor(max_workers=3)  # 设置最大工作线程数为3，可以根据需求调整

# 定义线程锁
retries_lock = threading.Lock()

# 日志文件和目标目录的映射
log_dirs = {
    "/tmp/rsfile/py/2020.09/2020.09_0051": "/tmp/2020.09.51",
}

# 重试次数和等待时间
max_retries = 3  # 最大重试次数
retry_interval = 300  # 5分钟等待时间，单位是秒


# 设置 Webhook 地址
url = "https://oapi.dingtalk.com/robot/send?access_token=c54fa6837d584b0abc56c0a7d0456ca37d59213dcc7ea3f6f104b20de3c71284"
secret = "SEC9de9f15e7d9bc3be3c0c5f50adcf283ff26189940919486b9cdb0feda9ee45b1"

# 初始化机器人
bot = DingtalkChatbot(webhook=url, secret=secret)


def nowTime():
    now = datetime.now()
    # 将时间格式化为字符串
    formatted_time = now.strftime("%Y-%m-%d %H:%M:%S")
    return formatted_time


# 发送钉钉通知的函数
def send_dingtalk_alert(message):
    try:
        # 发送请求
        bot.send_text(message)
        print(message)
    except Exception as e:
        error_message = f"发送钉钉通知时发生异常：{e}"
        print(error_message)
        logging.error(error_message)


def transfer_file(local_file, target_dir, local_log_file):
    for i in range(len(local_file)):
        file_path = local_file[i]
        source_file = os.path.basename(file_path)
        target_file = os.path.join(target_dir, source_file)

        retries = 0
        while retries < max_retries:
            try:
                # 使用rsync传输文件
                rsync_command = [
                    "rsync",
                    "-caz",  # 添加-c, -a, -z 选项
                    "--timeout=300",  # 添加超时选项
                    "--partial",  # 添加续传选项
                    "--append",  # 添加追加选项
                    "-e",
                    "ssh -p 13901 -i /root/.ssh/id_rsa",  # 使用SSH密钥认证
                    file_path,
                    f"{source_server['host']}:{target_file}",
                ]
                subprocess.run(rsync_command, check=True)
                print(f"{local_log_file} 正在传输文件: {source_file}")

                # 保存成功传输的文件索引
                # 传输成功，使用线程锁更新重试次数
                with retries_lock:
                    retries = 0  # 传输成功，重置重试计数
                # start_index = i
                # print(f"start_index={start_index}")
                index = i + 1
                print(f"index={index}")
                print(f"len(local_file)={len(local_file)}")

                # 如果已经成功传输了所有文件，则直接跳过
                if index >= len(local_file):
                    current_time = nowTime()
                    access_message = f"*{current_time}，{local_log_file} 所有文件已成功传输，请关注！*"
                    print(access_message)
                    send_dingtalk_alert(access_message)
                    return

                break  # 传输成功，退出重试循环

            except Exception as e:
                current_time = nowTime()
                error_message = f"{local_log_file} 文件 {source_file} 传输错误: {e}"
                print(error_message)
                logging.error(error_message)
                access_message = (
                    f"*{current_time}，{local_log_file} 文件 {source_file} 传输失败，请关注！*"
                )
                send_dingtalk_alert(access_message)
                # 记录传输进度
                # start_index = i
                # print(f"start_index={start_index}")

                # 使用线程锁增加重试计数
                with retries_lock:
                    retries += 1
                if retries < max_retries:
                    print(
                        f"{current_time}，{local_log_file} 文件 {source_file} 传输失败，等待 {retry_interval} 秒后重试..."
                    )
                    time.sleep(retry_interval)  # 休眠5分钟后重试
                else:
                    current_time = nowTime()
                    print("无法连接，发送钉钉通知...")
                    access_message = f"*{current_time}，{local_log_file} 文件 {source_file} 传输失败，达到最大重试次数，无法恢复，请关注！*"
                    send_dingtalk_alert(access_message)
                    return


def main():
    # 遍历每个日志文件和目标目录的映射
    for local_log_file, target_dir in log_dirs.items():
        try:
            # 读取需要传输的文件列表
            with open(local_log_file, "r") as file:
                files_to_transfer = file.read().splitlines()

            # 使用线程池并行传输
            executor.submit(
                transfer_file, files_to_transfer, target_dir, local_log_file
            )

        except Exception as e:
            print(f"遇到错误: {e}")
            continue

    # 关闭线程池
    executor.shutdown()


if __name__ == "__main__":
    main()
